package org.flashbrighton.as3bots.events
{
	import Box2D.Collision.b2ContactPoint;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.Contacts.b2ContactResult;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2ContactListener;
	
	import org.flashbrighton.as3bots.models.BotModel;
	import org.flashbrighton.as3bots.models.WallModel;

	public class ContactListener extends b2ContactListener
	{
		public override function Add(point:b2ContactPoint):void
		{
			// actions when something collides
			//trace("add");
 		}
 
 
	  public override function Persist(point:b2ContactPoint):void
	  {
	 		// actions when things keep contact
	 		//trace("persist");
	  }
	 
	 
	  public override function Remove(point:b2ContactPoint):void
	  {
	 		// actions when something uncollide - yep, just made that word up
	  }
	  
	  
	  public override function Result(point:b2ContactResult):void
	  {
	  	//trace("result");
	 		notifyCollidables(point);
	  }
	  
	  
	  private function notifyCollidables(point:b2ContactResult):void
		{
			var bot1:BotModel = point.shape1.m_body.m_userData as BotModel;
			var bot2:BotModel = point.shape2.m_body.m_userData as BotModel;
			var contactPos:b2Vec2 = point.position;
			var impulse:Number = point.normalImpulse / 45;
			var hitPos1:Number;
			var hitPos2:Number;
			var health1:Number;
			var health2:Number;
			var maxHitScore:int = 100;
			
			// Ignore persistant collisions
			if (impulse < 0.09) return;
			
			if (bot1 == null)
			{
				// Bot has hit a wall.
				hitPos2 = getHitPos(point.shape2.m_body, contactPos);
								
				health2 = 0//Math.round(Math.abs(hitPos2) * -maxHitScore * impulse);
				
				bot2.energy += health2;
				bot2.logic.notify(new BotEvent(BotEvent.HIT, hitPos2, health2, WallModel.COLLIDABLE_TYPE));
				return;
			}
			
			hitPos1 = getHitPos(point.shape1.m_body, contactPos);
			hitPos2 = getHitPos(point.shape2.m_body, contactPos);
			
			health1 = Math.round(Math.abs(hitPos1) * -maxHitScore * impulse);
			health2 = Math.round(Math.abs(hitPos2) * -maxHitScore * impulse);

			bot1.energy += health1;
			bot2.energy += health2;
			bot1.logic.notify(new BotEvent(BotEvent.HIT, hitPos1, health1, BotModel.COLLIDABLE_TYPE));			
			bot2.logic.notify(new BotEvent(BotEvent.HIT, hitPos2, health2, BotModel.COLLIDABLE_TYPE));
 		}
 		
	  
	  /**
		 * Finds the value based on where a bot gets hit (0 to 1).
		 */
		private function getHitPos(bot:b2Body, contactPos:b2Vec2):Number
		{
			var botPos:b2Vec2 = bot.GetWorldCenter();
			var botAngle:Number = bot.GetAngle();
			var PI:Number = Math.PI;
			var twoPI:Number = PI * 2;
			
			botAngle += PI;
			botAngle %= twoPI;
			if (botAngle < 0) botAngle += twoPI;
			botAngle -= PI;
			
			var hitAngle:Number = Math.atan2(contactPos.y - botPos.y, contactPos.x - botPos.x) - botAngle;
			var hitPos:Number = hitAngle/Math.PI;
			if (hitPos > 1) hitPos -= 2;
			if (hitPos < -1) hitPos += 2;

			return hitPos;
		}
		
	}
}